package com.xz.simplerpc.rpc.protocol;

import com.xz.simplerpc.constants.Constants;
import com.xz.simplerpc.extension.URL;
import com.xz.simplerpc.registry.Registry;
import com.xz.simplerpc.registry.RegistryDirectory;
import com.xz.simplerpc.registry.ZookeeperRegistry;
import com.xz.simplerpc.rpc.api.Exporter;
import com.xz.simplerpc.rpc.api.Invoker;
import com.xz.simplerpc.rpc.api.Protocol;
import com.xz.simplerpc.rpc.api.RpcException;
import com.xz.simplerpc.rpc.invokers.FailoverClusterInvoker;
import com.xz.simplerpc.rpc.proxy.JdkProxyFactory;
import com.xz.simplerpc.utils.NetUtils;

/**
 * Created by fingal on 2018/1/6.
 */
public class RegistryProtocol implements Protocol {
    private Protocol protocol;

    private JdkProxyFactory jdkProxyFactory = new JdkProxyFactory();

    public void setProtocol(Protocol protocol) {
        this.protocol = protocol;
    }

    @Override
    public int getDefaultPort() {
        return 9090;
    }

    @Override
    public <T> Exporter<T> export(Invoker<T> invoker, URL url) throws RpcException {
        //1.export service
        doExportLocal(invoker, url);
        //2.register service
        registry(invoker, url);
        return null;
    }

    private <T> void doExportLocal(Invoker<T> invoker, URL url) {
        URL providerUrl = URL.valueOf(url.getParameterAndDecoded(Constants.EXPORT_KEY));
        protocol.export(invoker, providerUrl);
    }

    private <T> void registry(Invoker<T> invoker, URL url) {
        Registry registry = new ZookeeperRegistry(url);
        URL registryUrl = URL.valueOf(url.getParameterAndDecoded(Constants.EXPORT_KEY));
        registry.register(registryUrl);
    }

    @Override
    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
        Registry registry = new ZookeeperRegistry(url);
        RegistryDirectory directory = new RegistryDirectory(type, url);
        directory.setRegistry(registry);
        URL subscribeUrl = new URL(Constants.CONSUMER_PROTOCOL, NetUtils.getLocalHost(), 0, type.getName(), url.getParameters());

        registry.register(subscribeUrl.addParameters(Constants.CATEGORY_KEY, Constants.CONSUMERS_CATEGORY));

        directory.subscribe(subscribeUrl.addParameter(Constants.CATEGORY_KEY, Constants.PROVIDERS_CATEGORY));

        return new FailoverClusterInvoker<T>(directory);
    }

    @Override
    public void destroy() {

    }
}
